package com.xxl.job.executor.core.config;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import com.xxl.job.core.handler.impl.MethodJobHandler;
import com.xxl.job.executor.annotation.AsyncCommonJob;
import com.xxl.job.executor.annotation.AsyncJob;
import com.xxl.job.executor.annotation.SimpleAsyncJob;
import com.xxl.job.executor.xxljob.autoregister.enums.XxlExecutorRouteStrategyEnum;
import com.xxl.job.executor.xxljob.autoregister.service.IXxlJobAutoRegister;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author lukaidong
 * @date 2024/02/25
 * @description
 */
@DependsOn({"xxlJobExecutor"})// 让其在执行器注册完成后执行
@Configuration
public class JobHandlerRegister implements ApplicationContextAware {

    private final XxlJobSpringExecutor xxlJobSpringExecutor;
    private final IXxlJobAutoRegister xxlJobAutoRegister;

    public JobHandlerRegister(XxlJobSpringExecutor xxlJobSpringExecutor, IXxlJobAutoRegister xxlJobAutoRegister) {
        this.xxlJobSpringExecutor = xxlJobSpringExecutor;
        this.xxlJobAutoRegister = xxlJobAutoRegister;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        applicationContext.getBeansOfType(Object.class).values().parallelStream()
                .forEach(bean -> Arrays.stream(bean.getClass().getMethods()).parallel().forEach(method -> {
                    AsyncJob asyncJob = method.getAnnotation(AsyncJob.class);
                    if (asyncJob != null) {
                        registerTask(asyncJob, bean, method);
                    }
                    SimpleAsyncJob simpleAsyncJob = method.getAnnotation(SimpleAsyncJob.class);
                    if (simpleAsyncJob != null) {
                        registerSimpleAsyncJob(simpleAsyncJob, bean, method);
                    }
                    AsyncCommonJob asyncCommonJob = method.getAnnotation(AsyncCommonJob.class);
                    if (asyncCommonJob != null) {
                        registerCommonTask(asyncCommonJob, bean, method);
                    }
                }));

    }

    private void registerCommonTask(AsyncCommonJob asyncCommonJob, Object bean, Method method) {
        // 1、注册执行器
        String jobName = asyncCommonJob.jobName();
        String cron = "0/10 * * * * ?";
        XxlJobSpringExecutor.registJobHandler(jobName, new MethodJobHandler(bean, method, null, null));

        // 2、注册任务 并启动
        xxlJobAutoRegister.registerOrStartJob(jobName, cron, XxlExecutorRouteStrategyEnum.SHARDING_BROADCAST);
    }

    private void registerSimpleAsyncJob(SimpleAsyncJob simpleAsyncJob, Object bean, Method method) {
        // 1、注册执行器
        String jobName = simpleAsyncJob.jobName();
        String cron = "0/10 * * * * ?";
        XxlJobSpringExecutor.registJobHandler(jobName, new MethodJobHandler(bean, method, null, null));

        // 2、注册任务 并启动
        xxlJobAutoRegister.registerOrStartJob(jobName, cron, XxlExecutorRouteStrategyEnum.CONSISTENT_HASH);
    }

    private void registerTask(AsyncJob asyncJob, Object bean, Method method) {
        // 1、注册执行器
        String jobName = asyncJob.jobName();
        String cron = "30/20 * * * * ?";
        XxlJobSpringExecutor.registJobHandler(jobName, new MethodJobHandler(bean, method, null, null));

        // 2、注册任务 并启动
        xxlJobAutoRegister.registerOrStartJob(jobName, cron, XxlExecutorRouteStrategyEnum.SHARDING_BROADCAST);
    }
}
